home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / dateimanager / browserii_v3_09 / sources / for.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  21KB  |  747 lines

  1. /*
  2.  *  Copyright © 1992-94 by S.R. & P.C.
  3.  *
  4.  *  Created:    30 Mar 1992  18:26:36
  5.  *  Modified:   09 Nov 1994  23:11:45
  6.  *
  7.  *  Make>> rx BumpRev For 3 8
  8.  *  Make>> sc <file>.c
  9.  *  Make>> slink LIB:cs.o <file>.o SC SD BATCH NOICONS TO <file> LIB LIB:c.lib
  10.  *  Make>> protect <file> P ADD
  11.  *
  12.  *
  13.  *    30/03/1992: V1.0 (Pierre Carrette)
  14.  *        Simple version with template: "Args/M,ALL/S,DONTFAIL/S,DO/K/A/F"
  15.  *  4/07/1994: V2.2 (Sylvain Rougier)
  16.  *      No longer add the name of the object if no '%%' present
  17.  *  5/07/1994: V3.0
  18.  *      Add the 'Quiet' option not to print hierarchy (but still print FileType if asked)
  19.  *      Now work as it should always work: don't scan all the directory if no pattern
  20.  *      but scan all subdir if 'All' option specified.
  21.  *      Add the 'GivePathName' option to provide a Full Path arguments to the command.
  22.  *      No longuer add '"' around the file name. User can type '"%%"' if he need it.
  23.  *  7/07/1994 V3.1
  24.  *      If a full pathname file entry was specified, For don't find it type. fixed
  25.  *  15/07/1994 V3.2
  26.  *      Guru if a single file was suplied. fixed
  27.  *      Now FullPathArgs realy work
  28.  *      Don't put optimize or it guru ! (see note)
  29.  *  31/07/1994 V3.3
  30.  *      Check the stack size because it need at least 8192 (probably !...)
  31.  *      put optimize again. just to see.
  32.  *  07/08/1994 V3.4
  33.  *      Remove optimize because the sasc bug still here
  34.  *      correct some error int the doc ( the '*' was incorrectly used instead of the '"')
  35.  *  21/08/1994 V3.5
  36.  *      Now use StackSwap() to avoid stack pb
  37.  *  22/09/1994 V3.6    (Pierre Carrette is back :-)
  38.  *        Major code cleanup. No more need StackSwap(). Bug fixes in template. whatis.library now Optional.
  39.  *        Inverted 'Quiet' to 'Verbose'. Changed 'VNFileType' to more comprehensive 'FileTypeVar' keyword.
  40.  *        Changed 'GivePathName' to 'FullPathArgs'.
  41.  *      FileTypeVar was not set if Showbytes was off.
  42.  *      Showbytes/ShowFileType is now off if no Cmd supplied.
  43.  *        'Type' argument syntax simplified. now:  "#text,!source c"
  44.  *        MatchFileType() bug fix. "#text,!source c" was not working!!
  45.  *        SAS Optimisation now works!!!
  46.  *  22/09/1994 V3.7
  47.  *        Recompiled with new version of c.lib which had a bug for 'ENV:' var parsing
  48.  *  09/11/1994 V3.8
  49.  *        Bug fix. File UnLock()ed before processed so that command can open it for writing.
  50.  */
  51.  
  52. #include <clib.h>
  53. #include <libraries/WhatIsBase.h>
  54. #include <proto/WhatIs.h>
  55. #include "For_rev.h"
  56.  
  57. // Startup Modules...
  58. CliArgs; ReadEnvArgs("For");
  59.  
  60. static char Version[] = VERSTAG;
  61.  
  62. STRPTR Template = "\
  63. Pattern/A/M,Files/K,Dirs/K,Since/K,Before/K,MinSize/K/N,MaxSize/K/N,\
  64. PosProtect/K,NegProtect/K,Type/K,All/S,ASync/S,ReadSize/K/N,ShowBytes/K/N,\
  65. D=Deep/K/N,SFT=ShowFileType/S,FTV=FileTypeVar/K,FPA=FullPathArgs/S,Verbose/S,Do/K/F";
  66.  
  67. STRPTR CliHelp = VERS" ("DATE") © Sylvain Rougier & Pierre Carrette.\n\
  68. Usage: For <Pattern> [Files <MATCH|YES|NO>] [Dirs <MATCH|YES|NO>]\n\
  69. [Since <Date>] [Before <Date>] [MinSize <Number>] [MaxSize <Number>]\n\
  70. [PosProtect <L|C|H|S|P|A|R|W|E|D>] [NegProtect <L|C|H|S|P|A|R|W|E|D>]\n\
  71. [Type <[#=SUB,~=EXLC]FileType0,,,FileType15>] [All] [ASync] [ReadSize]\n\
  72. [ShowBytes] [Deep] [ShowFileType] [FileTypeVar <var name>] [FullPathArgs]\n\
  73. [DO <Command [args] [,Command [args] [,...]]>]\n";
  74.  
  75. #define ARG_Template        0
  76. #define ARG_Files            1
  77. #define ARG_Dirs            2
  78. #define ARG_Since            3
  79. #define ARG_Before            4
  80. #define ARG_MinSize            5
  81. #define ARG_MaxSize            6
  82. #define ARG_PosProtect        7
  83. #define ARG_NegProtect        8
  84. #define ARG_Type            9
  85. #define ARG_ALL                10
  86. #define ARG_ASYNC            11
  87. #define ARG_READSIZE        12
  88. #define ARG_SHOWBYTES        13
  89. #define ARG_DEEPWHATIS        14
  90. #define ARG_SHOWFILETYPE    15
  91. #define ARG_FileTypeVar        16
  92. #define ARG_FullPathArgs    17
  93. #define ARG_Verbose            18
  94. #define ARG_CMD                19
  95. #define ARG_ENDARG            20
  96.  
  97.  
  98. struct Library *WhatIsBase;
  99.  
  100.  
  101. #define MAX_PATHLEN        256
  102. #define MAX_CMDLEN         512
  103.  
  104. /* char used in the filetype spec string */
  105. #define NOTFileType        '~'
  106. #define WITHSubTypes    '#'
  107.  
  108. /*******************************************************/
  109. /* not in dos.h !! */
  110. #define    FIBB_HOLD        7
  111. #define    FIBF_HOLD        (1<<FIBB_HOLD)
  112.  
  113. /* it is my own definition: not standard */
  114. #define    FIBB_COMMENT    8
  115. #define    FIBF_COMMENT    (1<<FIBB_COMMENT)
  116. #define    FIBB_LINK        9
  117. #define    FIBF_LINK        (1<<FIBB_LINK)
  118.  
  119.  
  120. #define PATTERN_BUF_SIZE    40
  121. #define MAX_FTS                16    /* Max FileTypeSpec in SelectInfo */
  122.  
  123. struct FileTypeSpec {
  124.     FileType fs_FileType;
  125.     UWORD fs_Flags;
  126. };
  127.  
  128. /* FileTypeSpec flags */
  129. #define FTSF_EXCLUDETYPE    0x0001    /* Exclude this type (otherwise include) */
  130. #define FTSF_WITHSUBTYPES    0x0002    /* Affect Include/Exclude to subtypes */
  131.  
  132.  
  133. struct SelectInfo {
  134.     UBYTE si_PatTok[PATTERN_BUF_SIZE];        /* PreParsed pattern                        */
  135.     LONG si_MinSize;                        /* Show files bigger than that              */
  136.     LONG si_MaxSize;                        /*   and smaller than that                  */
  137.     struct DateStamp si_SinceDate;            /* Show files newer than that               */
  138.     struct DateStamp si_BeforeDate;            /*   and older than that                    */
  139.     UWORD si_PosProtect;                    /* Show files that have these bits set       */
  140.     UWORD si_NegProtect;                    /* Show files that have these bits clear     */
  141.     struct FileTypeSpec si_FileTypes[MAX_FTS];    /* Include and Exclude file types         */
  142.     UWORD si_NumFts;                        /* Number of FileTypeSpec in previous array */
  143.     UWORD si_Flags;                            /* Flags. See below                         */
  144. };
  145.  
  146. /* SelectInfo flags */
  147.  
  148. #define SI_ALL_FILES        0x0001
  149. #define SI_MATCH_FILES        0x0002
  150. #define SI_ALL_DIRS            0x0004
  151. #define SI_MATCH_DIRS        0x0008
  152. #define SI_AFFECT_SUBDIRS    0x0010
  153. #define SI_NAME                0x0020
  154. #define SI_SIZE                0x0040
  155. #define SI_SINCEDATE        0x0080
  156. #define SI_BEFOREDATE        0x0100
  157. #define SI_POSPROTECTION    0x0200
  158. #define SI_NEGPROTECTION    0x0400
  159. #define SI_POSFILETYPE        0x0800
  160. #define SI_NEGFILETYPE        0x1000
  161.  
  162. #define SI_FILETYPE            (SI_POSFILETYPE|SI_NEGFILETYPE)
  163. #define SI_MATCHBITS        (SI_NAME|SI_SIZE|SI_SINCEDATE|SI_BEFOREDATE|SI_POSPROTECTION|SI_NEGPROTECTION|SI_FILETYPE)
  164.  
  165.  
  166. struct Opt {
  167.     BOOL Verbose;                /* Print some information */
  168.     BOOL Async;                    /* Run commands Asynchronously */
  169.     BOOL FullPathArgs;            /* Give Full PathName in Fmt ? */
  170.     BOOL ShowFileType;            /* Show FileType ? */
  171.     LONG ReadSize;                /* Size to read to find filetype */
  172.     ULONG Deep;                    /* deep level to find FileType */
  173.     UWORD Showbytes;            /* number of bytes to show */
  174.     STRPTR FileTypeVar;            /* Name of FileType var. no var if null */
  175. };
  176.  
  177.  
  178. /* return pointer to the first non blank char in a string, or to the '\0' if the string is empty */
  179.  
  180. static char *FirstNonBlank(char *buf)
  181. {
  182.     while (*buf && *buf == ' ')
  183.         buf++;
  184.     return buf;
  185. }
  186.  
  187.  
  188. /* check if buffer is empty or not */
  189.  
  190. static BOOL IsEmpty(char *buf)
  191. {
  192.     return (BOOL) ((*FirstNonBlank(buf)) ? FALSE : TRUE);
  193. }
  194.  
  195.  
  196. static BOOL String2Date(char *src, struct DateStamp *ds)
  197. {
  198.     struct DateTime *dt;
  199.     BOOL Ok = TRUE;
  200.     char *s1, *s2;
  201.     char buf[60];
  202.  
  203.     if (!(dt = AllocMem(sizeof(struct DateTime), MEMF_PUBLIC | MEMF_CLEAR)))
  204.          return FALSE;
  205.  
  206.     strcpy(buf, src);
  207.     s1 = s2 = FirstNonBlank(buf);
  208.     if (*s1) {
  209.         dt->dat_StrDate = s1;
  210.         while (*s2 && *s2 != ' ')
  211.             s2++;
  212.         if (*s2) {
  213.             *s2++ = '\0';
  214.             s2 = FirstNonBlank(s2);
  215.         }
  216.         if (*s2) {
  217.             dt->dat_StrTime = s2;
  218.             if (!StrToDate(dt))
  219.                 Ok = FALSE;
  220.         }
  221.         else if (!StrToDate(dt)) {
  222.             dt->dat_StrDate = NULL;
  223.             dt->dat_StrTime = s1;
  224.             if (!StrToDate(dt))
  225.                 Ok = FALSE;
  226.         }
  227.         if (Ok)
  228.             *ds = dt->dat_Stamp;
  229.     }
  230.     FreeMem(dt, sizeof(struct DateTime));
  231.  
  232.     return Ok;
  233. }
  234.  
  235.  
  236. static void PrintByte(UBYTE Buffer[], LONG BufLen, UBYTE Num)
  237. {
  238.     register short i;
  239.  
  240.     if (BufLen > 0) {
  241.         for (i = 0; i < Num && i < BufLen; i++)
  242.             Printf("%02lx", Buffer[i]);
  243.     }
  244. }
  245.  
  246.  
  247. /*
  248.  *  Parse a line that may contain comas. Backslash ('\') is the override char.
  249.  */
  250.  
  251. static UWORD ProtectBit(char P[])
  252. {
  253.     UWORD PB = 0;
  254.  
  255.     while (*P) {
  256.         switch (*P) {
  257.         case 'L':
  258.         case 'l':
  259.             PB |= FIBF_LINK;    /* another magic bit! */
  260.             break;
  261.         case 'C':
  262.         case 'c':
  263.             PB |= FIBF_COMMENT;    /* our magic bit! */
  264.             break;
  265.         case 'H':
  266.         case 'h':
  267.             PB |= FIBF_HOLD;
  268.             break;
  269.         case 'S':
  270.         case 's':
  271.             PB |= FIBF_SCRIPT;
  272.             break;
  273.         case 'P':
  274.         case 'p':
  275.             PB |= FIBF_PURE;
  276.             break;
  277.         case 'A':
  278.         case 'a':
  279.             PB |= FIBF_ARCHIVE;
  280.             break;
  281.         case 'R':
  282.         case 'r':
  283.             PB |= FIBF_READ;
  284.             break;
  285.         case 'W':
  286.         case 'w':
  287.             PB |= FIBF_WRITE;
  288.             break;
  289.         case 'E':
  290.         case 'e':
  291.             PB |= FIBF_EXECUTE;
  292.             break;
  293.         case 'D':
  294.         case 'd':
  295.             PB |= FIBF_DELETE;
  296.             break;
  297.         }
  298.         P++;
  299.     }
  300.     return PB;
  301. }
  302.  
  303.  
  304. static UWORD __inline EasyProtect(LONG Protection)
  305. {
  306.     return (UWORD) ((Protection ^ 0x0F) & 0x00FF);    /* Complement 4 lower bits so all work the same way */
  307. }
  308.  
  309.  
  310. static BOOL Match(struct SelectInfo * SelectInfo, struct FileInfoBlock *fib)
  311. {
  312.     if (fib->fib_DirEntryType < 0) {    /* this is a file */
  313.         if (SelectInfo->si_Flags & SI_ALL_FILES)
  314.             return TRUE;
  315.         else if (!(SelectInfo->si_Flags & SI_MATCH_FILES))
  316.             return FALSE;
  317.     }
  318.     else {                        /* Dir */
  319.         if (SelectInfo->si_Flags & SI_ALL_DIRS)
  320.             return TRUE;
  321.         else if (!(SelectInfo->si_Flags & SI_MATCH_DIRS))
  322.             return FALSE;
  323.     }
  324.     if (SelectInfo->si_Flags & SI_NAME) {
  325.         if (!MatchPatternNoCase(SelectInfo->si_PatTok, fib->fib_FileName))
  326.             return FALSE;
  327.     }
  328.     if (SelectInfo->si_Flags & SI_SINCEDATE) {
  329.         if (CompareDates(&SelectInfo->si_SinceDate, &fib->fib_Date) < 0)
  330.             return FALSE;
  331.     }
  332.     if (SelectInfo->si_Flags & SI_BEFOREDATE) {
  333.         if (CompareDates(&SelectInfo->si_BeforeDate, &fib->fib_Date) > 0)
  334.             return FALSE;
  335.     }
  336.     if (fib->fib_Size < SelectInfo->si_MinSize)
  337.         return FALSE;
  338.     if (SelectInfo->si_MaxSize && (fib->fib_Size > SelectInfo->si_MaxSize))
  339.         return FALSE;
  340.     {
  341.         UWORD Protection = EasyProtect(fib->fib_Protection);
  342.  
  343.         if (SelectInfo->si_Flags & SI_POSPROTECTION) {
  344.             if (!(Protection & SelectInfo->si_PosProtect))
  345.                 return FALSE;
  346.         }
  347.         if (SelectInfo->si_Flags & SI_NEGPROTECTION) {
  348.             if ((Protection & SelectInfo->si_NegProtect))
  349.                 return FALSE;
  350.         }
  351.     }
  352.     return TRUE;
  353. }
  354.  
  355.  
  356. static BOOL MatchFileType(struct SelectInfo *SelectInfo, struct FileInfoBlock *fib, FileType Type)
  357. {
  358.     if (WhatIsBase && (SelectInfo->si_Flags & SI_FILETYPE)) {
  359.         BOOL Sub = FALSE;
  360.         UWORD Flags, i;
  361.  
  362.         do {
  363.             for( i=0 ; i<SelectInfo->si_NumFts ; i++ ) {
  364.                 Flags = SelectInfo->si_FileTypes[i].fs_Flags;
  365.                 if ((!Sub || (Flags & FTSF_WITHSUBTYPES)) && !CmpFileType(SelectInfo->si_FileTypes[i].fs_FileType, Type))
  366.                     return (BOOL)((Flags & FTSF_EXCLUDETYPE) ? FALSE : TRUE);
  367.             }
  368.             Sub = TRUE;
  369.         } while (Type = ParentFileType(Type));
  370.         if (SelectInfo->si_Flags & SI_POSFILETYPE)
  371.             return FALSE;    /* no match within include FileTypes, exclude file */
  372.         else
  373.             return TRUE;    /* Only exclude types, and not found in them, include file */
  374.     }
  375.     return TRUE;
  376. }
  377.  
  378.  
  379. /*
  380.  *    Parse a line that may contain comas ','. Backslash ('\') is the override
  381.  *    char. This function replace comas by cariage returns so that SystemTags()
  382.  *    takes them as different command lines, just like a script file.
  383.  */
  384.  
  385. static void ParseCmdLine(char *cmd)
  386. {
  387.     char *s, *d, c;
  388.  
  389.     s = d = cmd;
  390.     while (c = *d++ = *s++) {
  391.         if (c == '\\')
  392.             *(d - 1) = *s++;
  393.         else if (c == ',')
  394.             *(d - 1) = '\n';
  395.     }
  396. }
  397.  
  398.  
  399. /* Replaces %% by %s, suitable for SPrintf() */
  400.  
  401. static void MakeFmt(char *CmdFmt, char *Cmd)
  402. {
  403.     char *s;
  404.  
  405.     strcpy(CmdFmt, Cmd);
  406.     ParseCmdLine(CmdFmt);        /* Replace , by \n to separate commands */
  407.     s = CmdFmt;
  408.     while (*s) {
  409.         if (*s == '%' && *(s + 1) == '%')
  410.             *(s + 1) = 's';
  411.         s++;
  412.     }
  413. }
  414.  
  415.  
  416. static LONG ExecuteCmd(char *Cmd, STRPTR StartPath, char *Name, struct Opt *Opt)
  417. {
  418.     char *CmdBuf, *CmdFmt, *NameBuf;
  419.     LONG rc = 20;
  420.     BOOL NoMem = TRUE;
  421.  
  422.     if (CmdBuf = AllocVec(MAX_CMDLEN, MEMF_ANY)) {
  423.         if (NameBuf = AllocVec(MAX_CMDLEN, MEMF_ANY)) {
  424.             if (CmdFmt = AllocVec(MAX_CMDLEN, MEMF_ANY)) {
  425.                 MakeFmt(CmdFmt, Cmd);
  426.                 if (Opt->FullPathArgs) {
  427.                     strcpy(NameBuf, StartPath);
  428.                     AddPart(NameBuf, Name, MAX_CMDLEN);
  429.                 }
  430.                 else
  431.                     strcpy(NameBuf, Name);
  432.                 /* Allow 5 %% in cmd */
  433.                 SPrintf(CmdBuf, CmdFmt, NameBuf, NameBuf, NameBuf, NameBuf, NameBuf);        /* build command line */
  434.                 if (Opt->Async) {
  435.                     SystemTags(CmdBuf,    SYS_Input, Open("*", MODE_OLDFILE),
  436.                                         SYS_Output, NULL,        // System() will open it
  437.                                         SYS_Asynch, TRUE,
  438.                                         SYS_UserShell, TRUE,
  439.                                         TAG_DONE);
  440.                     rc = 0;
  441.                 }
  442.                 else
  443.                     rc = SystemTags(CmdBuf, SYS_UserShell, TRUE, TAG_DONE);
  444.                 NoMem = FALSE;
  445.                 FreeVec(CmdFmt);
  446.             }
  447.             FreeVec(NameBuf);
  448.         }
  449.         FreeVec(CmdBuf);
  450.     }
  451.     if (NoMem)
  452.         PrintFault(ERROR_NO_FREE_STORE, "For");
  453.     else if (rc)
  454.         PrintFault(IoErr(), "For");
  455.     return rc;
  456. }
  457.  
  458.  
  459. static LONG ProcessEntry(struct SelectInfo *SelectInfo, struct FileInfoBlock *fib, STRPTR StartPath,
  460.                          STRPTR Name, UBYTE *FileData, struct Opt *Opt, STRPTR Cmd)
  461. {
  462.     LONG RC = 0, BytesRead = 0;
  463.     FileType Type = TYPE_UNSCANNED;
  464.  
  465.     if (WhatIsBase) {
  466.         if (Opt->Deep && fib->fib_DirEntryType <= 0) {
  467.             BPTR FH;
  468.  
  469.             if (FH = Open(Name, MODE_OLDFILE)) {
  470.                 BytesRead = Read(FH, FileData, Opt->ReadSize);
  471.                 FileData[BytesRead] = '\0';    /* whatis.library need that */
  472.                 Type = WhatIsTags(Name, WI_Deep, Opt->Deep, WI_FIB, fib, WI_Buffer, FileData, WI_BufLen, BytesRead, TAG_DONE);
  473.                 Close(FH);
  474.             }
  475.         }
  476.         else
  477.             Type = WhatIsTags(Name, WI_Deep, LIGHTTYPE, WI_FIB, fib, TAG_DONE);
  478.     }
  479.     if (MatchFileType(SelectInfo, fib, Type)) {
  480.         if (WhatIsBase) {
  481.             STRPTR IDString;
  482.             BOOL CR = FALSE;
  483.  
  484.             IDString = GetIDString(Type);
  485.             if (Opt->ShowFileType) {
  486.                 Printf("%-12s %-32s", IDString, (Opt->Verbose) ? fib->fib_FileName : Name);
  487.                 CR = TRUE;
  488.             }
  489.             if (Opt->Showbytes && fib->fib_DirEntryType <= 0) {
  490.                 PrintByte(FileData, BytesRead, Opt->Showbytes);
  491.                 CR = TRUE;
  492.             }
  493.             if (CR)
  494.                 PutStr("\n");
  495.             if (Opt->FileTypeVar)
  496.                 SetVar(Opt->FileTypeVar, IDString, -1L, GVF_LOCAL_ONLY);
  497.         }
  498.         if (Cmd)
  499.             RC = ExecuteCmd(Cmd, StartPath, Name, Opt);
  500.     }
  501.     return RC;
  502. }
  503.  
  504.  
  505. static LONG ProcessEntryPattern(struct AnchorPath *AP, struct SelectInfo *SelectInfo, struct Opt *Opt,
  506.                                 STRPTR StartPath, STRPTR Pattern, UBYTE *FileData, STRPTR Cmd)
  507. {
  508.     BOOL DoIt = TRUE;
  509.     LONG RC=0, MatchErr;
  510.  
  511.     for (MatchErr = MatchFirst(Pattern, AP); RC == 0 && MatchErr == 0; MatchErr = MatchNext(AP)) {
  512.         if (AP->ap_Flags & APF_DIDDIR) {
  513.             if (Opt->Verbose)
  514.                 Printf("%s\n", AP->ap_Buf);
  515.             DoIt = FALSE;                    /* Dir processed before entering it, don't process it twice */
  516.             AP->ap_Flags &= ~APF_DIDDIR;    /* clear the completed directory flag */
  517.         }
  518.         else if (AP->ap_Info.fib_DirEntryType > 0) {
  519.             if (SelectInfo->si_Flags & SI_AFFECT_SUBDIRS) {
  520.                 if (Opt->Verbose)
  521.                     Printf("%s\n", AP->ap_Buf);
  522.                 AP->ap_Flags |= APF_DODIR;    /* make Matchext() enter the directory */
  523.             }
  524.             else
  525.                 AP->ap_Flags &= ~APF_DODIR;    /* RESET this bit after MatchFirst/MatchNext to AVOID entering a dir. */
  526.         }
  527.  
  528.         /* Here is code for handling each particular file */
  529.         if (DoIt && Match(SelectInfo, &AP->ap_Info))
  530.             RC = ProcessEntry(SelectInfo, &AP->ap_Info, StartPath, AP->ap_Buf, FileData, Opt, Cmd);
  531.         DoIt = TRUE;
  532.     }
  533.     MatchEnd(AP);
  534.     if (MatchErr != ERROR_NO_MORE_ENTRIES)
  535.         PrintFault(MatchErr, "For");
  536.     return RC;
  537. }
  538.  
  539.  
  540. LONG Main(char *ArgV[], struct WBStartup *WBenchMsg)
  541. {
  542.     LONG rc = RETURN_OK;
  543.     char *StartPath = NULL, *Buffer = NULL;
  544.     struct FileInfoBlock *fib = NULL;
  545.     struct SelectInfo SelectInfo;
  546.     struct Opt Opt;
  547.     UBYTE *FileData;
  548.  
  549.     WhatIsBase = OpenLibrary("whatis.library", 3L);
  550.     memset(&SelectInfo, 0, sizeof(SelectInfo));
  551.     memset(&Opt, 0, sizeof(struct Opt));
  552.  
  553.     if (ArgV[ARG_Files]) {
  554.         if (!Stricmp(ArgV[ARG_Files], "MATCH"))
  555.             SelectInfo.si_Flags |= SI_MATCH_FILES;
  556.         else if (!Stricmp(ArgV[ARG_Files], "YES"))
  557.             SelectInfo.si_Flags |= SI_ALL_FILES;
  558.     }
  559.     else                        /* set default */
  560.         SelectInfo.si_Flags |= SI_MATCH_FILES;
  561.     if (ArgV[ARG_Dirs]) {
  562.         if (!Stricmp(ArgV[ARG_Dirs], "MATCH"))
  563.             SelectInfo.si_Flags |= SI_MATCH_DIRS;
  564.         else if (!Stricmp(ArgV[ARG_Dirs], "YES"))
  565.             SelectInfo.si_Flags |= SI_ALL_DIRS;
  566.     }
  567.     else                        /* set default */
  568.         SelectInfo.si_Flags |= SI_MATCH_DIRS;
  569.     if (ArgV[ARG_Since]) {
  570.         struct DateStamp DateStamp;
  571.  
  572.         String2Date(ArgV[ARG_Since], &DateStamp);
  573.         SelectInfo.si_SinceDate = DateStamp;
  574.         SelectInfo.si_Flags |= SI_SINCEDATE;
  575.     }
  576.     if (ArgV[ARG_Before]) {
  577.         struct DateStamp DateStamp;
  578.  
  579.         String2Date(ArgV[ARG_Before], &DateStamp);
  580.         SelectInfo.si_BeforeDate = DateStamp;
  581.         SelectInfo.si_Flags |= SI_BEFOREDATE;
  582.     }
  583.     if (ArgV[ARG_MinSize])
  584.         SelectInfo.si_MinSize = *(ULONG *) ArgV[ARG_MinSize];
  585.     if (ArgV[ARG_MaxSize])
  586.         SelectInfo.si_MaxSize = *(ULONG *) ArgV[ARG_MaxSize];
  587.     if (ArgV[ARG_PosProtect]) {
  588.         SelectInfo.si_Flags |= SI_POSPROTECTION;
  589.         SelectInfo.si_PosProtect = ProtectBit(ArgV[ARG_PosProtect]);
  590.     }
  591.     if (ArgV[ARG_NegProtect]) {
  592.         SelectInfo.si_Flags |= SI_NEGPROTECTION;
  593.         SelectInfo.si_NegProtect = ProtectBit(ArgV[ARG_NegProtect]);
  594.     }
  595.     if (ArgV[ARG_Type] && WhatIsBase) {
  596.         char IDType[100];
  597.         UBYTE NumFT = 0;
  598.         char *c, *i;
  599.  
  600.         for (c = ArgV[ARG_Type]; *c && NumFT < MAX_FTS && rc == 0;) {
  601.             switch (*c) {
  602.             case NOTFileType:    // ~
  603.                 SelectInfo.si_FileTypes[NumFT].fs_Flags |= FTSF_EXCLUDETYPE;
  604.                 break;
  605.             case WITHSubTypes:    // #
  606.                 SelectInfo.si_FileTypes[NumFT].fs_Flags |= FTSF_WITHSUBTYPES;
  607.                 break;
  608.             default:
  609.                 i = IDType;
  610.                 while (*c && *c != ',' && i < IDType+100-1)
  611.                     *i++ = *c++;    // copy until ',' or end of string
  612.                 *i = '\0';            // nul terminate the string
  613.                 if (SelectInfo.si_FileTypes[NumFT].fs_Flags & FTSF_EXCLUDETYPE)
  614.                     SelectInfo.si_Flags |= SI_NEGFILETYPE;
  615.                 else
  616.                     SelectInfo.si_Flags |= SI_POSFILETYPE;
  617.                 SelectInfo.si_FileTypes[NumFT].fs_FileType = GetIDType(IDType);
  618.                 if (TYPE_UNKNOWNIDSTRING == SelectInfo.si_FileTypes[NumFT].fs_FileType) {
  619.                     Printf("Unknown FileType: %s\n", IDType);
  620.                     rc = 21;    // Hack to prevent PrintFault('no memory')
  621.                 }
  622.                 NumFT++;
  623.             }
  624.             if (*c)
  625.                 c++;
  626.         }
  627.         SelectInfo.si_NumFts = NumFT;
  628.     }
  629.     if (ArgV[ARG_ALL])
  630.         SelectInfo.si_Flags |= SI_AFFECT_SUBDIRS;
  631.  
  632.     Opt.Async = (BOOL) ArgV[ARG_ASYNC];
  633.     Opt.ReadSize = (ArgV[ARG_READSIZE]) ? *(LONG *) ArgV[ARG_READSIZE] : 488;
  634.     Opt.Deep = (ArgV[ARG_DEEPWHATIS]) ? *(LONG *) ArgV[ARG_DEEPWHATIS] : LIGHTTYPE;
  635.     if (ArgV[ARG_SHOWBYTES]) {
  636.         Opt.Showbytes = (UBYTE) (*(LONG *) ArgV[ARG_SHOWBYTES]);
  637.         Opt.Deep = DEEPTYPE;
  638.     }
  639.     Opt.ShowFileType = (BOOL) ArgV[ARG_SHOWFILETYPE];
  640.     Opt.FileTypeVar = (STRPTR) ArgV[ARG_FileTypeVar];
  641.     Opt.FullPathArgs = (BOOL) ArgV[ARG_FullPathArgs];
  642.     Opt.Verbose = (BOOL) ArgV[ARG_Verbose];
  643.  
  644.     if (rc == 0 && !(Buffer = AllocVec(MAX_PATHLEN, MEMF_ANY)))
  645.         rc = RETURN_FAIL;
  646.  
  647.     if (rc == 0 && !(StartPath = AllocVec(MAX_PATHLEN, MEMF_ANY)))
  648.         rc = RETURN_FAIL;
  649.  
  650.     if (rc == 0 && !(fib = AllocVec(sizeof(struct FileInfoBlock), MEMF_ANY)))
  651.         rc = RETURN_FAIL;
  652.  
  653.     if (rc == 0 && (FileData = AllocVec(Opt.ReadSize + 1, MEMF_ANY))) {
  654.         struct AnchorPath *AP;
  655.  
  656.         if (AP = AllocVec(sizeof(struct AnchorPath) + MAX_PATHLEN, MEMF_ANY)) {
  657.             LONG IsWild;
  658.             STRPTR Elmt;
  659.             UBYTE i;
  660.  
  661.             if (Opt.FullPathArgs)
  662.                 NameFromLock(((struct Process *)SysBase->ThisTask)->pr_CurrentDir, StartPath, MAX_PATHLEN);
  663.             else
  664.                 StartPath[0] = '\0';
  665.  
  666.             for (i = 0; rc == 0 && (Elmt = ((char **) ArgV[ARG_Template])[i]); i++) {
  667.                 memset(AP, 0, sizeof(struct AnchorPath) + MAX_PATHLEN);
  668.                 AP->ap_BreakBits = SIGBREAKF_CTRL_C;    /* Break on these bits  */
  669.                 AP->ap_Strlen = MAX_PATHLEN;
  670.                 /*
  671.                  *  For wildcard matching with ALL flag set, two situations are handled differently
  672.                  *    1.    foo#?/bar
  673.                  *    2.    foobar#?
  674.                  *    In the first case, a standard MatchFirst()/MatchNext() is used.
  675.                  *    For the second one, if 'ALL' option is on, the pattern is replaced with "#?"
  676.                  *    so that all directories are parsed, and then files filtered out by the more
  677.                  *    powerfull function Match()
  678.                  */
  679.                 IsWild = ParsePatternNoCase(Elmt, Buffer, MAX_PATHLEN);
  680.                 if (ArgV[ARG_ALL] && IsWild == 1 && FilePart(Elmt) == Elmt) {
  681.                     SelectInfo.si_Flags |= SI_NAME;
  682.                     strcpy(SelectInfo.si_PatTok, Buffer);
  683.                     rc = ProcessEntryPattern(AP, &SelectInfo, &Opt, StartPath, "#?", FileData, ArgV[ARG_CMD]);
  684.                 }
  685.                 else {
  686.                     BPTR L;
  687.  
  688.                     switch (IsWild) {
  689.                     case 1:
  690.                         /*
  691.                          *    Pattern
  692.                          *    Dir1/Dir2/Pattern
  693.                          *    Vol:Dir1/Dir2/Pattern
  694.                          */
  695.                         rc = ProcessEntryPattern(AP, &SelectInfo, &Opt, StartPath, Elmt, FileData, ArgV[ARG_CMD]);
  696.                         break;
  697.                     case 0:
  698.                         if (L = Lock(Elmt, SHARED_LOCK)) {
  699.                             long ok;
  700.  
  701.                             ok = Examine(L, fib);
  702.                             UnLock(L);    // UnLock so that command can open file for writing
  703.                             if (ok) {
  704.                                 if (ArgV[ARG_ALL] && fib->fib_DirEntryType >= 0) {    // This is a dir
  705.                                     strcpy(Buffer, Elmt);
  706.                                     AddPart(Buffer, "#?", MAX_PATHLEN);
  707.                                     rc = ProcessEntryPattern(AP, &SelectInfo, &Opt, StartPath, Buffer, FileData, ArgV[ARG_CMD]);
  708.                                 }
  709.                                 else
  710.                                     rc = ProcessEntry(&SelectInfo, fib, StartPath, Elmt, FileData, &Opt, ArgV[ARG_CMD]);
  711.                             }
  712.                             else {
  713.                                 PrintFault(IoErr(), Elmt);
  714.                                 rc = RETURN_FAIL;
  715.                             }
  716.                         }
  717.                         else if (ArgV[ARG_CMD])        // Arg does not exists, allow:  For 1 2 3 DO Echo %%
  718.                             rc = ExecuteCmd(ArgV[ARG_CMD], StartPath, Elmt, &Opt);
  719.                         else                            
  720.                             rc = RETURN_WARN;
  721.                         break;
  722.                     default:
  723.                         PrintFault(IoErr(), Elmt);
  724.                         rc = RETURN_FAIL;
  725.                     }
  726.                 }
  727.             }
  728.             FreeVec(AP);
  729.         }
  730.         FreeVec(FileData);
  731.     }
  732.     else if (rc == 21)
  733.         rc = RETURN_FAIL;
  734.     else
  735.         PrintFault(ERROR_NO_FREE_STORE, "For");
  736.     if (fib)
  737.         FreeVec(fib);
  738.     if (Buffer)
  739.         FreeVec(Buffer);
  740.     if (StartPath)
  741.         FreeVec(StartPath);
  742.     if (WhatIsBase)
  743.         CloseLibrary(WhatIsBase);
  744.     return rc;
  745. }
  746.  
  747.